package Server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.LinkedList;

public class ClientHandler implements Runnable{
	private ObjectInputStream input;
	private ObjectOutputStream output;
	private commandList engine;
	private DataAccess da;
	private String welcome;
	private boolean hasDbAccess = false;

	private LinkedList<Integer> ds;

	public ClientHandler(Socket socket){
		welcome = "You have succesfully established a connection with the server!";

		this.da = new DataAccess();
		ds = new LinkedList<Integer>();

		try{
			this.output = new ObjectOutputStream(socket.getOutputStream());
			output.flush();
			this.input = new ObjectInputStream(socket.getInputStream());
		}catch(Exception e){
			e.printStackTrace();
		}
		this.engine = new commandList(output);
		new Thread(this).start();
	}

	private String hasDb() {
		return "Database: " + hasDbAccess;
	}

	private void closeConnections(){
		da.release();
		da = null;
		ds = null;	
		hasDbAccess = false;
	}

	public void run() {
		String commandString = "";

		try {
			if (da.open()) {
				hasDbAccess = true;
			}			
			output.writeObject(welcome);			
			output.writeObject(hasDb());			
			output.flush();			
		} catch (IOException e2) {
			//connection failed
		}

		while(true){			
			try {				
				commandString = (String) input.readObject();

				String[] commands = commandString.split(" ");
				String c = commands[0].trim();
				String firstChar = c.substring(0,1);
				c = firstChar.toUpperCase() + c.substring(1).toLowerCase();

				ClassLoader loader =  this.getClass().getClassLoader();	
				Command command = (Command) loader.loadClass("Command."+ c + "Command").newInstance();

				cmdArguments args = new cmdArguments();
				args.da = da;
				args.db = hasDbAccess;
				args.ds = ds;
				args.commands = commands;
				args.commandList = engine;

				command.setArgs(args);
				engine.addCommand(command);		

			} catch (IOException e) {
				if (hasDbAccess) {
					closeConnections();
				}
				//lSystem.out.println("It is very likely that a client gave us a close command...");				
				break;
			} catch (ClassNotFoundException e) {
				try { 
					output.writeObject(commandString + " is not a valid command");
				} catch (Exception e1) {

				}
			} catch (InstantiationException e) {
				if (hasDbAccess) {
					closeConnections();
				}
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				if (hasDbAccess) {
					closeConnections();
				}
				e.printStackTrace();
			} catch (Exception e) {
				if (hasDbAccess) {
					closeConnections();
				}
				System.out.println("Lost a client... It never said goodbye. :(");
				break;
			}
		}
	}
}